// Copyright 2021 Tencent. All rights reserved.
// Author: billbai <billbai@tencent.com>

#ifndef OCSENGINE_RFIX_RFIXFORTEST_H_
#define OCSENGINE_RFIX_RFIXFORTEST_H_

#import <Foundation/Foundation.h>

#import <RFIX/RFIXBuildConfig.h>
#import <RFIX/RFIX.h>

/// NOTE: !!! 该文件中的接口供本地调试使用，请*不要*在正式外发版本中调用

/// 已废弃，请使用 RFIXRegisterSymbols
RFIX_EXPORT void RFIXRegisterAppCFunction(NSString *cFunctionName, void *cFunctionPointer)
    DEPRECATED_MSG_ATTRIBUTE("Please use RFIXRegisterSymbols");

/// 已废弃，请使用 RFIXRegisterSymbols
RFIX_EXPORT void RFIXRegisterAppVar(NSString *varName, void *varPointer)
    DEPRECATED_MSG_ATTRIBUTE("Please use RFIXRegisterSymbols");

/// ⚠️ Licensed 版本没有该接口
/// 加载补丁包（zip 路径）, 会检查 Version.json
/// 0.6.0 及更高版本加载补丁时，会*同步发联网请求*后台加载补丁策略，检测是否允许加载补丁。
/// （网络异常/超时情况下默认允许加载，最多会阻塞3秒）
/// Note: 有时 Xcode 不会更新 bundle 中的 zip 文件，此时可以尝试修改 zip 文件名以强制更新文件。
/// 具体错误码详见 https://iwiki.woa.com/pages/viewpage.action?pageId=971971559
#if !RFIX_BUILD_CONFIG_IS_LICENSED
RFIX_EXPORT NSUInteger RFIXLoadResourcePack(NSString *filePath);
#endif // !RFIX_BUILD_CONFIG_IS_LICENSED

/// 获取当前线程抛 oc 异常时虚拟机调用栈信息
RFIX_EXPORT NSString *RFIXGetCurrentThreadVMExceptionCallStackInfo(void);

/// 获取当前线程虚拟机调用栈信息
RFIX_EXPORT NSString *RFIXGetCurrentThreadVMStackInfo(void);

#pragma mark - Trace Log API
/// TraceLog API
/// 开启 TraceLog 后，RFIX 会将以下时间记录到 trace log 文件：
///   - 加载了哪些补丁文件
///   - 新增了哪些动态类/动态 Protocol
///   - 覆盖替换或添加了哪些方法到 objc 类中
///   - 执行了哪些补丁中的方法
///   - 补丁中的方法在执行过程中，调用了哪些 objc 方法
///   - 部分关键错误信息
/// 在进行本地补丁验证时，建议打开 TraceLog 功能，并检查 TraceLog 内容，确认：
///   - 补丁中的代码已被测试用例执行到
///   - 补丁中的代码在执行过程中调用了预期的 ObjC 方法
///   - 补丁中的代码已被正确加载
///
/// ⚠️ NOTE: Trace Log 功能仅供 Debug 目的使用。绝对*不可以* 在线上打开 TraceLog 功能。
///           Trace Log 信息仅供人类阅读，日志格式可能会有变化，且不会提前通知。
///           Trace Log 功能开启后，因为会有日志文本写入（文件 IO），
///           补丁执行性能会大幅下降，并可能改变多线程环境下的运行时序。

/// Trace Log 功能是否开启
/// 默认为关闭
/// ⚠️ NOTE: 请不要在线上打开 TraceLog 功能，本功能仅供本地测试。
/// returns: YES TraceLog 功能已开启
///          NO  TraceLog 功能已关闭
RFIX_EXPORT BOOL RFIXGetIsTraceLogEnabled(void);

/// 开启 Trace Log 功能
/// 默认为关闭
/// ⚠️ NOTE: 请不要在线上打开 TraceLog 功能，本功能仅供本地测试。
RFIX_EXPORT void RFIXEnableTraceLog(void);

/// 关闭 Trace Log 功能
/// 默认为关闭
/// ⚠️ NOTE: 请不要在线上打开 TraceLog 功能，本功能仅供本地测试。
RFIX_EXPORT void RFIXDisableTraceLog(void);

/// 获取 Trace Log 文件路径。文件位于 tmp 目录，获取路径后，
/// 调用方需要将文件自行移动到目标位置，或者立即展示文件内容。
/// 文件格式为 txt 文本文件
/// ⚠️ NOTE: 请不要在线上打开 TraceLog 功能，本功能仅供本地测试。
RFIX_EXPORT NSString *RFIXGetTraceLogFilePath(void);


RFIX_EXPORT NSNotificationName const RFIXFoundTotsFileNotification;

#if RFIX_BUILD_CONFIG_IS_LICENSED
#pragma mark - Licensed Debug API
/// 注意，仅 License 版本有以下 debug 接口，非 License 版本请使用 RFIXLoadResourcePack 接口加载调试补丁

/// 启用 Licensed Debug 模式
/// ⚠️ NOTE: 请不要在线上打开 Licensed Debug 模式，本功能仅供本地测试。
/// 请在 RFIXSDKStart **之前**调用
/// 该接口仅在 License 版本中生效，非 License 版本无效
/// 打开 Licensed Debug 模式后， RFIXSDKStart 不会加载从 Shiply 平台下发的补丁，也不会尝试请求补丁任务配置。
/// 可以使用 RFIXRequestAndLoadLicensedDebugTask 接口加载 Licensed Debug 补丁
RFIX_EXPORT void RFIXEnableLicensedDebugMode(void);

/// 查询是否开启 Licensed Debug 模式
RFIX_EXPORT BOOL RFIXLicensedDebugModeIsEnabled(void);

/// Licensed Debug 模式错误码
typedef NS_ENUM(NSInteger, RFIXLicensedDebugErrorCode) {
  RFIXLicensedDebugErrorOK = 0, // no error
  RFIXLicensedDebugErrorNotEnabled = 5001, // 未开启 Licensed Debug 模式, 请先调用 RFIXEnableLicensedDebugMode()
  RFIXLicensedDebugErrorTaskIDInvalid = 5002, // taskID 无效
  RFIXLicensedDebugErrorRequestFailed = 5003, // 请求失败
  RFIXLicensedDebugErrorLoadFailed = 5004, // 加载失败
  RFIXLicensedDebugErrorIsRequesting = 5005, // 正在请求中, 不要重复请求
  RFIXLicensedDebugErrorTaskNotFound = 5006, // 任务未找到
  RFIXLicensedDebugErrorInvalidResponse = 5007, // 无效的响应
  RFIXLicensedDebugErrorDownloadFailed = 5008, // 下载失败
  RFIXLicensedDebugErrorAlreadyLoaded = 5009, // 已加载调试
};

/// 请求并加载 Licensed Debug 补丁
/// 该接口仅在 License 版本中生效，非 License 版本无效
/// 请在 RFIXSDKStart **之后**调用
/// 该接口会请求 Licensed Debug 补丁任务，并加载补丁
/// |taskID| 为 Licensed Debug 补丁任务 ID
/// |callback| 为请求结果回调
/// ⚠️ NOTE: 请不要在线上调用该接口，本功能仅供本地测试。
typedef void (^RFIXRequestAndLoadLicensedDebugTaskCompletion)(BOOL success, NSError *error);
RFIX_EXPORT void RFIXRequestAndLoadLicensedDebugTask(NSString *taskID, RFIXRequestAndLoadLicensedDebugTaskCompletion callback);

/*
 // 以下所有字段都可能不存在（例如没有请求过调试任务或未开启调试模式），访问前请判断是否存在
 // 如果正在请求中，则只有 taskID 字段存在
 @{
 @"taskID": @"123456",
 @"success": @(YES),
 @"error": <NSError>
 @"loadResultCode": @(<加载错误码>),
 @"extraMessage": @"<额外信息>",
 }
 */
/// 获取 Licensed Debug 任务信息
/// 该接口仅在 License 版本中生效，非 License 版本无效
/// 返回值为 NSDictionary 类型，包含以下信息（以下所有字段都可能不存在，访问前请判断是否存在）
/// - taskID: 当前 Licensed Debug 任务 ID
/// - success: 是否请求和加载成功
/// - error: 请求加载错误信息（成功时没有 error 字段）
/// - loadResultCode: 加载结果错误码
/// - extraMessage: 额外信息 （例如加载错误码为 15 时，这里列出未注册的符号）
/// ⚠️ NOTE: 请不要在线上调用该接口，本功能仅供本地测试。
RFIX_EXPORT NSDictionary *RFIXGetLicensedDebugTaskInfo(void);

#endif  // RFIX_BUILD_CONFIG_IS_LICENSED

#endif  // OCSENGINE_RFIX_RFIXFORTEST_H_
